import type { ComponentInternalInstance } from 'vue'
import { isArray, isObject } from 'xe-utils'
import { useDictOptions } from '@/hooks'

const FORM_TYPE = [
  'Input',
  'Select',
  'RadioGroup',
  'CheckboxGroup',
  'DictSelect',
  // 'ElInputNumber',
  // 'ElRadioGroup',
  // 'ElCheckboxGroup',
  // 'ElSelect',
  // 'ElCascader',
  // 'ElSwitch',
  // 'ElSlider',
  // 'ElTimeSelect',
  // 'ElTimePicker',
  // 'ElDatePicker',
  // 'ElRate',
  // 'ElColorPicker',
  // 'ElTransfer'
]

export const getFormVNode = (instance: ComponentInternalInstance): ComponentInternalInstance => {
  if (instance.type.name === 'Form') {
    return instance
  }

  return getFormVNode(instance.parent!)
}

export const getFormItemInputVNode = (list?: VNode[]): any => {
  if (!list) {
    return
  }
  let vNode
  for (let index = 0; index < list.length; index++) {
    vNode = list[index]
    if (typeof vNode.type === 'object' && FORM_TYPE.includes((vNode.type as any).name)) {
      return vNode
    }
    vNode = getFormItemInputVNode(vNode.children as VNode[])
    if (vNode) {
      return vNode
    }
  }
  return vNode
}

const getFirstSubVNode = (vNode: any) => vNode?.children.default()?.[0]

const getOptions = (vNode: any): { label: string, value: string }[] => {
  // console.log(vNode?.children?.default())
  if (vNode.props.options) {
    return vNode.props.options
  }
  return vNode?.children?.default().map(item => ({
    label: item.props.label,
    value: item.props.value,
  }))
}

export const getValueByPath = <T = any>(
  obj: Record<string, any> | undefined,
  path: string | undefined,
): T | undefined => {
  if (!obj || !path) {
    return undefined
  }
  path = path.replace(/\[(\w+)\]/g, '.$1')
  let keys: string[] = []
  if (path.length && path[0] === '\'' && path.length && path[path.length - 1] === '\'') {
    keys = [path.substring(1, path.length - 1)]
  } else {
    keys = path.split('.')
  }
  if (keys.length === 0) {
    return undefined
  }
  let temp = obj

  for (let i = 0; i < keys.length; i++) {
    if ((!isObject(temp) && !isArray(temp)) || !keys[i]) {
      return undefined
    }
    if (i !== keys.length - 1) {
      temp = temp[keys[i]] as any
    } else {
      return temp[keys[i]] as T
    }
  }

  return undefined
}

export const getDisplayValue = (fieldValue: any, inputVNode: any) => {
  const inputType = inputVNode?.type?.name || 'UNKNOWN'
  switch (inputType) {
    case 'DictSelect': {
      const dictCode = inputVNode.props.code
      const options: Array<any> = useDictOptions(dictCode)
      return Array.isArray(fieldValue)
        ? options.filter(item => fieldValue.includes(item.value)).map(item => item.label).join(',')
        : options.find(item => item.value === fieldValue)?.label
    }
    case 'Select': {
      const options = getFirstSubVNode(inputVNode).children?.map((_vNode: any) => _vNode.props) || {}
      return Array.isArray(fieldValue)
        ? options.filter(item => fieldValue.includes(item.value)).map(item => item.label).join(',')
        : options.find((item: any) => item.value === fieldValue)?.label
    }
    case 'RadioGroup':
      return getOptions(inputVNode)?.find(item => item.value === fieldValue)?.label
    case 'CheckboxGroup':
      return getOptions(inputVNode)
        ?.filter(item => fieldValue?.includes(item.value))
        ?.map(item => item.label)
        ?.join(',')
    default:
      return fieldValue
  }
}
